"""
Flask 主应用文件
包含所有API路由和业务逻辑
"""
from flask import Flask, request, jsonify
from functools import wraps
from config import Config
from models import db, User, Image, ImageVersion, UserCollect, CollectItem, UserAction, Admin, UserVIP
from datetime import datetime
import re
import jwt
from passlib.hash import argon2

# ----------------- 初始化应用 -----------------
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)

# ----------------- 辅助函数 -----------------
def validate_phone(phone):
    """验证中国大陆手机号格式（11位数字且以1开头）"""
    return re.match(r"^1[3-9]\d{9}$", phone) is not None

def generate_token(user_id):
    """生成JWT令牌"""
    return jwt.encode(
        {'user_id': user_id, 'exp': datetime.utcnow() + app.config['JWT_EXPIRATION']},
        app.config['SECRET_KEY'],
        algorithm='HS256'
    )

def token_required(f):
    """身份验证装饰器"""
    @wraps(f)
    def decorated(*args, **kwargs):
        if app.config['TESTING_MODE']:
            user_id = request.args.get('user_id')
            if not user_id:
                return jsonify({'error': '测试模式需要user_id参数'}), 401
            user = User.query.get(user_id)
            if not user:
                return jsonify({'error': '用户不存在'}), 404
            request.user = user
            return f(*args, **kwargs)
        
        token = request.headers.get('Authorization')
        if not token:
            return jsonify({'error': '缺少访问令牌'}), 401
        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
            user = User.query.get(data['user_id'])
            if not user:
                raise ValueError('用户不存在')
            request.user = user
        except jwt.ExpiredSignatureError:
            return jsonify({'error': '令牌已过期'}), 401
        except Exception as e:
            return jsonify({'error': f'无效令牌: {str(e)}'}), 401
        return f(*args, **kwargs)
    return decorated

# ----------------- 用户模块 -----------------
@app.route('/register', methods=['POST'])
def register():
    """用户注册接口"""
    data = request.json
    required_fields = ['username', 'password', 'phone_number']
    for field in required_fields:
        if field not in data:
            return jsonify({'error': f'缺少必要字段: {field}'}), 400
    
    if not validate_phone(data['phone_number']):
        return jsonify({'error': '手机号格式无效'}), 400

    if User.query.filter_by(user_name=data['username']).first():
        return jsonify({'error': '用户名已被占用'}), 409
    if User.query.filter_by(phone_number=data['phone_number']).first():
        return jsonify({'error': '手机号已注册'}), 409

    try:
        new_user = User(
            user_name=data['username'],
            phone_number=data['phone_number'],
            membership_type='member'
        )
        new_user.set_password(data['password'])
        db.session.add(new_user)
        db.session.commit()
        return jsonify({
            'user_id': new_user.user_id,
            'username': new_user.user_name,
            'membership_type': new_user.membership_type
        }), 201
    except Exception as e:
        db.session.rollback()
        return jsonify({'error': f'注册失败: {str(e)}'}), 500

@app.route('/login', methods=['POST'])
def login():
    """用户登录接口"""
    data = request.json
    if 'username' not in data or 'password' not in data:
        return jsonify({'error': '需要用户名和密码'}), 400
    
    user = User.query.filter(
        (User.user_name == data['username']) |
        (User.phone_number == data['username'])
    ).first()
    
    if not user or not user.check_password(data['password']):
        return jsonify({'error': '用户名或密码错误'}), 401
    
    return jsonify({
        'user_id': user.user_id,
        'username': user.user_name,
        'token': generate_token(user.user_id)
    }), 200

# ----------------- 图片模块 -----------------
@app.route('/images', methods=['GET'])
def get_images():
    """
    获取所有图片信息（包含最新版本的oss路径）
    修改点：通过关联查询获取oss_path
    """
    # 查询图片及其最新版本
    images = db.session.query(
        Image.image_id,
        Image.image_title,
        Image.image_description,
        ImageVersion.oss_path
    ).join(
        ImageVersion,
        Image.image_id == ImageVersion.image_id
    ).order_by(ImageVersion.upload_at.desc()).distinct(Image.image_id).all()

    return jsonify([{
        'image_id': img.image_id,
        'title': img.image_title,
        'description': img.image_description,
        'oss_path': img.oss_path  # 来自image_version_db
    } for img in images]), 200

# ----------------- 收藏夹模块 -----------------
@app.route('/collect', methods=['POST', 'DELETE', 'GET'])
@token_required
def manage_collection():
    """
    收藏夹管理接口
    POST: 创建收藏夹或收藏项
    DELETE: 删除收藏夹或收藏项
    GET: 查询用户所有收藏夹
    """
    user = request.user

    # 创建操作
    if request.method == 'POST':
        data = request.json
        if not data:
            return jsonify({'error': '缺少请求体'}), 400
        
        # 创建收藏夹
        if 'collect_name' in data:
            if not data['collect_name']:
                return jsonify({'error': '收藏夹名称不能为空'}), 400
            try:
                new_collect = UserCollect(
                    user_id=user.user_id,
                    collect_name=data['collect_name']
                )
                db.session.add(new_collect)
                db.session.commit()
                return jsonify({
                    'collect_id': new_collect.usercollect_id,
                    'collect_name': new_collect.collect_name
                }), 201
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': str(e)}), 500
        
        # 创建收藏项（确保items_name字段存在）
        elif 'usercollect_id' in data and 'image_id' in data and 'items_name' in data:
            collect = UserCollect.query.filter_by(
                usercollect_id=data['usercollect_id'],
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在或无权访问'}), 404
            
            image = Image.query.get(data['image_id'])
            if not image:
                return jsonify({'error': '图片不存在'}), 404
            
            try:
                new_item = CollectItem(
                    usercollect_id=data['usercollect_id'],
                    image_id=data['image_id'],
                    items_name=data['items_name']  # 确保字段存在
                )
                db.session.add(new_item)
                db.session.commit()
                return jsonify({
                    'item_id': new_item.items_id,
                    'image_id': new_item.image_id,
                    'items_name': new_item.items_name
                }), 201
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': str(e)}), 500
        
        else:
            return jsonify({'error': '缺少必要参数（需 usercollect_id, image_id, items_name）'}), 400
        
    # 删除操作
    elif request.method == 'DELETE':
        target_id = request.args.get('id')
        target_type = request.args.get('type')
        
        if not target_id or not target_type:
            return jsonify({'error': '需要id和type参数'}), 400
        
        # 删除收藏夹
        if target_type == 'collect':
            collect = UserCollect.query.filter_by(
                usercollect_id=target_id,  # 确保字段名正确
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '收藏夹不存在或无权访问'}), 404
            
            try:
                CollectItem.query.filter_by(usercollect_id=target_id).delete()
                db.session.delete(collect)
                db.session.commit()
                return jsonify({'message': '收藏夹删除成功'}), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': str(e)}), 500
        
        # 删除收藏项
        elif target_type == 'item':
            item = CollectItem.query.get(target_id)
            if not item:
                return jsonify({'error': '收藏项不存在'}), 404
            
            collect = UserCollect.query.filter_by(
                usercollect_id=item.usercollect_id,
                user_id=user.user_id
            ).first()
            if not collect:
                return jsonify({'error': '无权操作此收藏项'}), 403
            
            try:
                db.session.delete(item)
                db.session.commit()
                return jsonify({'message': '收藏项删除成功'}), 200
            except Exception as e:
                db.session.rollback()
                return jsonify({'error': str(e)}), 500
        
        else:
            return jsonify({'error': '无效的操作类型'}), 400

    # 查询收藏夹（返回新增的 items_name）
    elif request.method == 'GET':
        collects = UserCollect.query.filter_by(user_id=user.user_id).all()
        result = []
        for col in collects:
            items = CollectItem.query.filter_by(usercollect_id=col.usercollect_id).all()
            result.append({
                'id': col.usercollect_id,
                'name': col.collect_name,
                'items': [{
                    'item_id': item.items_id,
                    'image_id': item.image_id,
                    'items_name': item.items_name  # 确保字段存在
                } for item in items]
            })
        return jsonify(result), 200

# ----------------- 评论模块--------------------------
@app.route('/comment', methods=['POST', 'GET', 'DELETE'])
@token_required
def comment_management():
    """
    评论管理接口
    POST: 发表评论（同步更新image_db评论次数）
    GET: 获取指定图片的评论列表
    DELETE: 删除评论（同步更新image_db评论次数）
    """
    user = request.user
    data = request.json if request.method == 'POST' else None

    # ----------------- 发表评论 -----------------
    if request.method == 'POST':
        # 参数校验
        if 'image_id' not in data or 'comment' not in data:
            return jsonify({'error': '需要image_id和comment参数'}), 400
        
        # 查询图片是否存在
        image = Image.query.get(data['image_id'])
        if not image:
            return jsonify({'error': '图片不存在'}), 404
        
        try:
            # 创建评论记录
            new_comment = UserAction(
                user_id=user.user_id,
                action_type='comment',
                image_id=data['image_id'],
                comment_context=data['comment'],
                create_at=datetime.now()
            )
            db.session.add(new_comment)

            # ----------------- 关键修正点 -----------------
            # 初始化comment_time为0（如果字段为空）
            if image.comment_time is None:
                image.comment_time = 0
            # 评论次数加1（直接操作整数）
            image.comment_time += 1
            # -------------------------------------------

            db.session.add(image)
            db.session.commit()
            return jsonify({
                'comment_id': new_comment.action_id,
                'content': new_comment.comment_context
            }), 201
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': str(e)}), 500

    # ----------------- 查询评论 -----------------
    elif request.method == 'GET':
        image_id = request.args.get('image_id')
        if not image_id:
            return jsonify({'error': '需要image_id参数'}), 400
        
        # 获取所有评论按时间倒序排列
        comments = UserAction.query.filter_by(
            image_id=image_id,
            action_type='comment'
        ).order_by(UserAction.create_at.desc()).all()
        
        return jsonify([{
            'id': c.action_id,
            'user_id': c.user_id,
            'content': c.comment_context,
            'time': c.create_at.isoformat()
        } for c in comments]), 200

    # ----------------- 删除评论 -----------------
    elif request.method == 'DELETE':
        comment_id = request.args.get('id')
        if not comment_id:
            return jsonify({'error': '需要评论ID'}), 400
        
        # 查询评论是否存在且用户有权操作
        comment = UserAction.query.filter_by(
            action_id=comment_id,
            user_id=user.user_id
        ).first()
        if not comment:
            return jsonify({'error': '评论不存在或无权操作'}), 404
        
        try:
            # 删除评论记录
            db.session.delete(comment)

            # 更新对应图片的评论次数
            image = Image.query.get(comment.image_id)
            # ----------------- 关键修正点 -----------------
            if image and image.comment_time > 0:  # 确保次数不低于0
                image.comment_time -= 1
            # -------------------------------------------
            
            db.session.add(image)
            db.session.commit()
            return jsonify({'message': '评论删除成功'}), 200
        except Exception as e:
            db.session.rollback()
            return jsonify({'error': str(e)}), 500
        
# ----------------- 启动应用 -----------------
if __name__ == '__main__':
    with app.app_context():
        db.create_all()  # 自动创建数据库表
    app.run(host='0.0.0.0', port=5000, debug=True)